home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1997 #1
/
Amiga Plus CD - 1997 - No. 01.iso
/
pd
/
programmierung
/
mesa-1.2.8
/
src
/
amigamesa.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-27
|
33KB
|
1,375 lines
/* $Id: AmigaMesa.c,v 1.7 Exp $ */
/*
* Mesa 3-D graphics library
* Copyright (C) 1995 Brian Paul (brianp@ssec.wisc.edu)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
$Log: AmigaMesa.c,v1.6 $
* Revision 1.7 1996/05/21 23:08:42 StefanZ
* A few bug and enforcer fixes
*
* Revision 1.6 1996/04/29 22:14:31 StefanZ
* BugFixes reported by by Daniel Jönsson
*
* Revision 1.5 1996/03/14 23:54:33 StefanZ
* Doublebuffer & Tmprastport seams to work (big speed improvment)
* a fastpolydraw is also implemented
*
* Revision 1.4 1996/03/07 16:55:04 StefanZ
* Much of the code works now (RGB mode is simulated) Doublebuffers... (didn't work)
*
* Revision 1.3 1996/02/29 02:12:45 StefanZ
* First sight of colors (even the right ones) maglight.c works
*
* Revision 1.2 1996/02/25 13:11:16 StefanZ
* First working version. Draws everything with the same color
* (Colormaping is now urgent needed)
*
* Revision 1.1 1996/02/23 22:01:15 StefanZ
* Made changes to match latest version of ddsample 1.5
*
* Revision 1.0 1996/02/21 11:01:15 StefanZ
* File created from ddsample.c ver 1.3 and amesa.c ver 1.5
* in a brave atempt to rebuild the amiga version
*
*/
/*
TODO:
Have two colortables in dubbelduffering so that it dont get deallocated when showing. (memory saving)
Dynamic allocate the vectorbuffer for polydrawing. (Speed improvment)
Draw lines insted off pixles in Write_monocolor_span.(speed improvment)
Use writepixelarray in sted of WritePixel in write_index_span & write_color_span. (speed improvment)
Check make_temp_Rport and dont use areafill if it fail's.
IDEAS:
Make drawing on a Cyber-GFX in full color. (If someone gave me a
gfx-card I would speed up on this :)
Make the gl a sharedlibrary. (Have ben started)
*/
/*
* Note that you'll usually have to flip Y coordinates since Mesa's
* window coordinates start at the bottom and increase upward. Most
* window system's Y-axis increases downward
*
* See dd.h for more device driver info.
* See the other device driver implementations for ideas.
*
* The Makefile should compile this module along with the rest of
* the core Mesa library.
*/
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include "gl/AmigaMesa.h"
#include "context.h"
#include "dd.h"
#include "xform.h"
#include "vb.h"
#define MAX_POLYGON 300
/**********************************************************************/
/***** Internal Data *****/
/**********************************************************************/
struct amigamesa_context * Current = NULL;
/**********************************************************************/
/***** Some Usefull code *****/
/**********************************************************************/
static struct RastPort *make_rastport( int width, int height, int depth );
static void destroy_rastport( struct RastPort *rp );
static BOOL make_temp_raster( struct RastPort *rp );
static void destroy_temp_raster( struct RastPort *rp );
static void AllocOneLine(struct amigamesa_context *AmigaMesaCreateContext);
static void FreeOneLine(struct amigamesa_context *AmigaMesaCreateContext);
#define c8to32(x) (((((((x)<<8)|(x))<<8)|(x))<<8)|(x))
__inline int RGBA(GLubyte r,GLubyte g,GLubyte b,GLubyte a)
{
int pen;
/*printf("RGBA(%d,%d,%d,%d)",r,g,b,a);getchar();*/
pen=ObtainBestPen(Current->window->WScreen->ViewPort.ColorMap,
c8to32((ULONG)r),c8to32((ULONG)g),c8to32((ULONG)b),
OBP_Precision,PRECISION_GUI,TAG_DONE);
if(!(pen==-1))
{
Current->mypen[pen]+=1;
}
else
{
pen=FindColor(Current->window->WScreen->ViewPort.ColorMap,
c8to32((ULONG)r),c8to32((ULONG)g),c8to32((ULONG)b),-1);
/* If all pen is no sharable take one */
/* kprintf("(no sharable pen)\n",pen);*/
}
/*printf("=%d\n",pen);*/
return pen;
}
__inline GLint FIXx(GLint x)
{
return(Current->left + x);
}
__inline GLint FIXy(GLint y)
{
return(Current->bottom - y);
}
/**********************************************************************/
/***** Miscellaneous device driver funcs *****/
/**********************************************************************/
static void afinish( void )
{
/* implements glFinish if possible */
}
static void aflush( void )
{
/* implements glFlush if possible */
}
static void aclear_index( GLuint index )
{
/* implement glClearIndex */
/* usually just save the value in the context struct */
/*printf("aclear_index=glClearIndex=%d\n",index);*/
Current->clearpixel=Current->penconv[index];
}
static void aclear_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
/* implement glClearColor */
/* color components are floats in [0,1] */
/* usually just save the value in the context struct */
/*printf("aclear_color=glClearColor(%d,%d,%d,%d)\n",r,g,b,a);*/
/* @@@ TODO FREE COLOR IF NOT USED */
Current->clearpixel=RGBA(r,g,b,a);
}
static void aclear( GLboolean all, GLint x, GLint y, GLint width, GLint height )
{
/*
* Clear the specified region of the color buffer using the clear color
* or index as specified by one of the two functions above.
* If all==GL_TRUE, clear whole buffer
*/
/*printf("aclear(%d,%d,%d,%d,%d)\n",all,x,y,width,height);*/
SetAPen(Current->rp,Current->clearpixel);
if(all)
{
RectFill(Current->rp,Current->left,Current->window->BorderTop,Current->left+Current->width-1,Current->bottom);
if (Current->rgb_flag)
{
int I;
for(I=0;I<=255;I++) /* Dealocate pens is in RGB mode */
{
while (Current->mypen[I]!=0) /* TODO This may free some others pen also */
{
Current->mypen[I]-=1;
ReleasePen(Current->window->WScreen->ViewPort.ColorMap,I);
}
}
}
}
else
{
if(Current->rp!=0)
{
/* printf("RectFill(0x%x,%d,%d,%d,%d)\n",Current->rp,FIXx(x),FIXy(y)-height,width,FIXy(y));*/
RectFill(Current->rp,FIXx(x),FIXy(y)-height,width,FIXy(y));
}
else
printf("Serius error Current->rp=0 detected in aclear() in file amigamesa.c\n");
}
}
static void aset_index( GLuint index )
{
/* Set the current color index. */
/*printf("aset_index(%d)\n",index);*/
Current->pixel = Current->penconv[index];
}
static void aset_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
/*printf("aset_color(%d,%d,%d,%d)\n",r,g,b,a);*/
/* Set the current RGBA color. */
/* r is in 0..CC.RedScale */
/* g is in 0..CC.GreenScale */
/* b is in 0..CC.BlueScale */
/* a is in 0..CC.AlphaScale */
Current->pixel = RGBA(r,g,b,a);
/*(a << 24) | (r << 16) | (g << 8) | b;*/
}
static GLboolean aindex_mask( GLuint mask )
{
/* implement glIndexMask if possible, else return GL_FALSE */
/*printf("aindex_mask(0x%x)\n",mask);*/
Current->rp->Mask = (UBYTE) mask;
return(GL_TRUE);
}
static GLboolean acolor_mask( GLboolean rmask, GLboolean gmask,
GLboolean bmask, GLboolean amask)
{
/* implement glColorMask if possible, else return GL_FALSE */
return(GL_FALSE);
}
static GLboolean alogicop( GLenum op )
{
/*
* Implements glLogicOp if possible. Return GL_TRUE if the device driver
* can perform the operation, otherwise return GL_FALSE. If GL_FALSE
* is returned, the logic op will be done in software by Mesa.
*/
return(GL_FALSE);
}
static void adither( GLboolean enable )
{
/* enable/disable dithering if applicable */
}
static GLboolean aset_buffer( GLenum mode )
{
/* set the current drawing/reading buffer, return GL_TRUE or GL_FALSE */
/* for success/failure */
/* amiga_setup_DD_pointers(); in ddsample is this right?????*/
/* printf("aset_buffer TODO\n");*/
/* TODO implemed a set of buffers */
if (mode==GL_FRONT)
{
return(GL_TRUE);
}
else if (mode==GL_BACK)
{
return(GL_TRUE);
}
else
{
return(GL_FALSE);
}
}
static void abuffer_size( GLuint *width, GLuint *height, GLuint *depth )
{
/* return the width, height and depth (bits/pixel) of the current buffer */
/* if anything special has to been done when the buffer/window is */
/* resized, do it now */
/* printf("abuffer_size\n");*/
if(!((*width=Current->width) ==(Current->window->Width - Current->window->BorderLeft - Current->window->BorderRight)&&
((*height=Current->height) ==(Current->window->Height - Current->window->BorderTop - Current->window->BorderBottom))))
{
FreeOneLine(Current);
Current->width =Current->window->Width - Current->window->BorderLeft - Current->window->BorderRight;
Current->height=Current->window->Height - Current->window->BorderTop - Current->window->BorderBottom;
Current->left = Current->window->BorderLeft;
Current->bottom = Current->window->Height - Current->window->BorderBottom - 1;
destroy_temp_raster( Current->rp); /* deallocate temp raster */
if (Current->db_flag)
{
if (Current->back_rp) /* Fix dubbel buffer */
{
destroy_rastport(Current->back_rp);
}
if((Current->back_rp = make_rastport(Current->window->Width,Current->window->Height,Current->depth))==NULL)
{
Current->rp = Current->front_rp;
printf("To little mem free. Couldn't allocate Dubblebuffer in this size.\n");
}
else
{
Current->rp=Current->back_rp;
}
}
if (Current->rgb_flag)
{
/* RGBA color buffers */
Current->gl_ctx->RGBAflag = GL_TRUE;
*depth= 24; /* TODO */
Current->depth =Current->depth = Current->window->RPort->BitMap->Depth;
}
else
{
/* CI color buffers */
Current->gl_ctx->RGBAflag = GL_FALSE;
*depth=Current->depth = Current->window->RPort->BitMap->Depth;
}
if(!make_temp_raster( Current->rp ))
printf("Error allocating TmpRasterPort\n");
AllocOneLine(Current);
}
}
/**********************************************************************/
/***** Accelerated point, line, polygon rendering *****/
/**********************************************************************/
static void afast_points_function( GLuint first, GLuint last )
{
/* Render a number of points by some hardware/OS accerated method */
int i,col;
/* printf("afast_points_function\n");*/
if (VB.MonoColor) {
/* draw all points using the current color (set_color) */
SetAPen(Current->rp,Current->pixel);
/* printf("VB.MonoColor\n");*/
for (i=first;i<=last;i++) {
if (VB.Unclipped[i]) {
/* compute window coordinate */
int x, y;
x =FIXx((GLint) (VB.Win[i][0]));
y =FIXy((GLint) (VB.Win[i][1]));
WritePixel(Current->rp,x,y);
/* printf("WritePixel(%d,%d)\n",x,y);*/
}
}
}
else {
/* each point is a different color */
/* printf("!VB.MonoColor\n");*/
for (i=first;i<=last;i++) {
/*if (VB.Unclipped[i])*/ {
int x, y;
x =FIXx((GLint) (VB.Win[i][0]));
y =FIXy((GLint) (VB.Win[i][1]));
col=*VB.Color[i];
SetAPen(Current->rp,Current->penconv[col]);
WritePixel(Current->rp,x,y);
/* printf("WritePixel(%d,%d)\n",x,y);*/
}
}
}
}
static points_func achoose_points_function( void )
{
/*printf("achoose_points_function\n");*/
/* Examine the current rendering state and return a pointer to a */
/* fast point-rendering function if possible. */
if (CC.Point.Size==1.0 && !CC.Point.SmoothFlag && CC.RasterMask==0
&& !CC.Texture.Enabled /*&& ETC, ETC */) {
return afast_points_function;
}
else {
return afast_points_function;
/* return NULL;*/
}
}
static void afast_line_function( GLuint v0, GLuint v1, GLuint pv )
{
/* Render a line by some hardware/OS accerated method */
int x0, y0, x1, y1;
/* printf("afast_line_function\n");*/
if (VB.MonoColor)
{
SetAPen(Current->rp,Current->pixel);
}
else
{
SetAPen(Current->rp,Current->penconv[*VB.Color[pv]]);
}
x0 = FIXx((int) (VB.Win[v0][0]));
y0 = FIXy((int) (VB.Win[v0][1]));
x1 = FIXx((int) (VB.Win[v1][0]));
y1 = FIXy((int) (VB.Win[v1][1]));
Move(Current->rp,x0,y0);
Draw(Current->rp,x1,y1);
}
static line_func achoose_line_function( void )
{
/*printf("achoose_line_function\n");*/
/* Examine the current rendering state and return a pointer to a */
/* fast line-rendering function if possible. */
if (CC.Line.Width==1.0 && !CC.Line.SmoothFlag && !CC.Line.StippleFlag
&& CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
&& !CC.Texture.Enabled /*&& ETC, ETC */ )
{
return afast_line_function;
}
else
{
return NULL;
}
}
/*
* Draw a filled polygon of a single color. If there is hardware/OS support
* for polygon drawing use that here. Otherwise, call a function in
* polygon.c to do the drawing.
*/
static void afast_polygon_function( GLuint n, GLuint vlist[], GLuint pv )
{
int i,j;
/* Render a line by some hardware/OS accerated method */
/* printf("afast_polygon_function\n");*/
if (VB.MonoColor)
{
SetAPen(Current->rp,Current->pixel);
}
else
{
SetAPen(Current->rp,Current->penconv[*VB.Color[pv]]);
}
AreaMove(Current->rp, FIXx((int) VB.Win[0][0]), FIXy( (int) VB.Win[0][1]));
for (i=1;i<n;i++)
{
j=vlist[i];
AreaDraw( Current->rp, FIXx((int) VB.Win[j][0]), FIXy( (int) VB.Win[j][1]));
}
AreaEnd( Current->rp );
}
static polygon_func achoose_polygon_function( void )
{
/* printf("achoose_polygon_function\n");*/
/* Examine the current rendering state and return a pointer to a */
/* fast polygon-rendering function if possible. */
if (!CC.Polygon.SmoothFlag && !CC.Polygon.StippleFlag
&& CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
&& !CC.Texture.Enabled /*&& ETC, ETC */ )
{
return afast_polygon_function;
/* return NULL;*/
}
else
{
return NULL;
}
}
/**********************************************************************/
/***** Write spans of pixels *****/
/**********************************************************************/
static void awrite_index_span( GLuint n, GLint x, GLint y,
const GLuint index[],
const GLubyte mask[] )
{
int i,ant;
UBYTE *dp;
/* printf("awrite_index_span(%d,%d,%d)\n",n,x,y);getchar(); */
y=FIXy(y);
x=FIXx(x);
if((dp = Current->imageline) && Current->tmpras)
{ /* if imageline allocated then use fastversion */
ant=0;
for (i=0;i<n;i++) /* draw pixel (x[i],y[i]) using index[i] */
{
if (mask[i])
{
ant++;
x++;
*dp++ = Current->penconv[index[i]];
}
else
{
if(ant)
WritePixelLine8(Current->rp,x,y,ant,Current->imageline,Current->tmpras);
dp=Current->imageline;
ant=0;
x++;
}
}
if(ant)
WritePixelLine8(Current->rp,x,y,ant,Current->imageline,Current->tmpras);
}
else
{ /* Slower */
for (i=0;i<n;i++,x++)
{
if (mask[i])
{
/* draw pixel (x[i],y[i]) using index[i] */
SetAPen(Current->rp,Current->penconv[index[i]]);
WritePixel(Current->rp,x,y);
}
}
}
}
static void awrite_monoindex_span(GLuint n,GLint x,GLint y,const GLubyte mask[])
{
int i;
/* printf("awrite_monoindex_span(%d,%d,%d)<\n",n,x,y);getchar(); */
SetAPen(Current->rp,Current->pixel);
y=FIXy(y);
x=FIXx(x);
for (i=0;i<n;i++,x++)
{
if (mask[i])
{
/* draw pixel (x[i],y[i]) using current color index */
WritePixel(Current->rp,x,y);
}
}
}
static void awrite_color_span( GLuint n, GLint x, GLint y,
const GLubyte red[], const GLubyte green[],
const GLubyte blue[], const GLubyte alpha[],
const GLubyte mask[] )
{
int i;
/* printf("awrite_color_span(%d,%d,%d)<\n",n,x,y); getchar(); */
y=FIXy(y);
x=FIXx(x);
if (mask)
{
/* draw some pixels */
for (i=0; i<n; i++, x++)
{
if (mask[i])
{
/* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */
SetAPen(Current->rp,RGBA(red[i],green[i],blue[i],alpha[i]));
WritePixel(Current->rp,x,y);
}
}
}
else
{
/* draw all pixels */
for (i=0; i<n; i++, x++)
{
/* draw pixel x,y using color red[i]/green[i]/blue[i]/alpha[i] */
SetAPen(Current->rp,RGBA(red[i],green[i],blue[i],alpha[i]));
WritePixel(Current->rp,x,y);
}
}
}
static void awrite_monocolor_span( GLuint n, GLint x, GLint y,
const GLubyte mask[])
{
int i;
/*printf("awrite_monocolor_span(%d,%d,%d)<<<<<<<\n",n,x,y); getchar(); */
y=FIXy(y);
x=FIXx(x);
SetAPen(Current->rp,Current->pixel);
for (i=0; i<n; i++, x++) {
if (mask[i]) {
WritePixel(Current->rp,x,y);
}
}
}
/**********************************************************************/
/***** Read spans of pixels *****/
/**********************************************************************/
static void aread_index_span( GLuint n, GLint x, GLint y, GLuint index[])
{
int i;
/*printf("aread_index_span>>\n");*/
y=FIXy(y);
x=FIXx(x);
for (i=0; i<n; i++,x++)
{
index[i] = ReadPixel(Current->rp,x,y);
}
}
static void aread_color_span( GLuint n, GLint x, GLint y,
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[] )
{
int i,col;
ULONG ColTab[3];
/*printf("aread_color_span>>\n");*/
y=FIXy(y);
x=FIXx(x);
for (i=0; i<n; i++, x++)
{
col=ReadPixel(Current->rp,x,y);
GetRGB32(Current->window->WScreen->ViewPort.ColorMap,col,1,ColTab);
red[i] = ColTab[0]>>24;
green[i] = ColTab[1]>>24;
blue[i] = ColTab[2]>>24;
alpha[i]=255;
}
}
/**********************************************************************/
/***** Write arrays of pixels *****/
/**********************************************************************/
static void awrite_index_pixels( GLuint n, const GLint x[], const GLint y[],
const GLuint index[], const GLubyte mask[] )
{
int i;
/*printf("awrite_index_pixels<\n");*/
for (i=0; i<n; i++) {
if (mask[i]) {
/* plot pixel x[i], y[i] using index[i] */
SetAPen(Current->rp,Current->penconv[index[i]]);
WritePixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
}
}
}
static void awrite_monoindex_pixels( GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
int i;
/*printf("awrite_monoindex_pixels<\n");*/
SetAPen(Current->rp,Current->pixel);
for (i=0; i<n; i++) {
if (mask[i]) {
/* write pixel x[i], y[i] using current index */
WritePixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
}
}
}
static void awrite_color_pixels( GLuint n, const GLint x[], const GLint y[],
const GLubyte r[], const GLubyte g[],
const GLubyte b[], const GLubyte a[],
const GLubyte mask[] )
{
int i;
/* printf("awrite_color_pixels<\n");*/
for (i=0; i<n; i++) {
if (mask[i]) {
/* write pixel x[i], y[i] using red[i],green[i],blue[i],alpha[i] */
SetAPen(Current->rp,RGBA(r[i],g[i],b[i],a[i]));
WritePixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
}
}
}
static void awrite_monocolor_pixels( GLuint n,
const GLint x[], const GLint y[],
const GLubyte mask[] )
{
int i;
/* printf("awrite_monocolor_pixels<\n");*/
SetAPen(Current->rp,Current->pixel);
for (i=0; i<n; i++) {
if (mask[i]) {
/* write pixel x[i], y[i] using current color*/
WritePixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
}
}
}
/**********************************************************************/
/***** Read arrays of pixels *****/
/**********************************************************************/
/* Read an array of color index pixels. */
static void aread_index_pixels( GLuint n, const GLint x[], const GLint y[],
GLuint index[], const GLubyte mask[] )
{
int i;
/* printf("aread_index_pixels-\n");*/
for (i=0; i<n; i++) {
if (mask[i]) {
/* index[i] = read_pixel x[i], y[i] */
index[i] = ReadPixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
}
}
}
static void aread_color_pixels( GLuint n, const GLint x[], const GLint y[],
GLubyte red[], GLubyte green[],
GLubyte blue[], GLubyte alpha[],
const GLubyte mask[] )
{
int i,col;
ULONG ColTab[3];
/* printf("aread_color_pixels-\n");*/
for (i=0; i<n; i++)
{
if (mask[i])
{
col=ReadPixel(Current->rp,FIXx(x[i]),FIXy(y[i]));
GetRGB32(Current->window->WScreen->ViewPort.ColorMap,col,1,ColTab);
red[i] = ColTab[0]>>24;
green[i] = ColTab[1]>>24;
blue[i] = ColTab[2]>>24;
alpha[i]=255;
}
}
}
/**********************************************************************/
/**********************************************************************/
/* org:static void setup_DD_pointers( void ) */
void amiga_setup_DD_pointers( void )
{
/* Initialize all the pointers in the DD struct. Do this whenever */
/* a new context is made current or we change buffers via set_buffer! */
DD.finish = afinish;
DD.flush = aflush;
DD.clear_index = aclear_index;
DD.clear_color = aclear_color;
DD.clear = aclear;
DD.index = aset_index;
DD.color = aset_color;
DD.index_mask = aindex_mask;
DD.color_mask = acolor_mask;
DD.logicop = alogicop;
DD.dither = adither;
DD.set_buffer = aset_buffer;
DD.buffer_size = abuffer_size;
DD.get_points_func = achoose_points_function;
DD.get_line_func = achoose_line_function;
DD.get_polygon_func = achoose_polygon_function;
/* Pixel/span writing functions: */
DD.write_color_span = awrite_color_span;
DD.write_monocolor_span = awrite_monocolor_span;
DD.write_color_pixels = awrite_color_pixels;
DD.write_monocolor_pixels = awrite_monocolor_pixels;
DD.write_index_span = awrite_index_span;
DD.write_monoindex_span = awrite_monoindex_span;
DD.write_index_pixels = awrite_index_pixels;
DD.write_monoindex_pixels = awrite_monoindex_pixels;
/* Pixel/span reading functions: */
DD.read_index_span = aread_index_span;
DD.read_color_span = aread_color_span;
DD.read_index_pixels = aread_index_pixels;
DD.read_color_pixels = aread_color_pixels;
}
/**********************************************************************/
/***** Amiga/Mesa Private Functions *****/
/**********************************************************************/
/*
* Create a new rastport to use as a back buffer.
* Input: width, height - size in pixels
* depth - number of bitplanes
*/
struct RastPort *make_rastport( int width, int height, int depth )
{
struct RastPort *rp;
struct BitMap *bm;
if (bm=AllocBitMap(width,height,depth,BMF_CLEAR|BMF_INTERLEAVED,0))
{
if (rp = (struct RastPort *) malloc( sizeof(struct RastPort)))
{
InitRastPort( rp );
rp->BitMap = bm;
return rp;
}
else
{
FreeBitMap(bm);
return 0;
}
}
else
return 0;
}
/*
* Deallocate a rastport.
*/
void destroy_rastport( struct RastPort *rp )
{
WaitBlit();
FreeBitMap( rp->BitMap );
free( rp );
}
/*
* Construct a temporary raster for use by the given rasterport.
* Temp rasters are used for polygon drawing.
*/
BOOL static make_temp_raster( struct RastPort *rp )
{
BOOL OK;
unsigned long width, height;
PLANEPTR p;
struct TmpRas *tmpras;
OK=TRUE;
if(rp==0)
{
printf("Zero rp\n");
return(FALSE);
}
width = rp->BitMap->BytesPerRow*8;
height = rp->BitMap->Rows;
/* allocate structures */
p = AllocRaster( width, height );
if(p!=0)
{
tmpras = (struct TmpRas *) AllocVec( sizeof(struct TmpRas),MEMF_ANY);
if(tmpras!=0)
{
if(InitTmpRas( tmpras, p, ((width+15)/16)*height ))
{
/* Current->tmpras=tmpras;*/
rp->TmpRas = tmpras;
}
else
OK=FALSE;
}
else
OK=FALSE;
}
else
return(FALSE);
if (OK)
return(TRUE);
else
{
printf("Error when allocationg TmpRas\n");
if (tmpras)
FreeVec(tmpras);
if (p)
FreeRaster(p,width, height);
return(FALSE);
}
}
BOOL allocarea(struct RastPort *rp )
{
BOOL OK;
struct AreaInfo *areainfo;
UWORD *pattern;
APTR vbuffer;
OK=TRUE;
areainfo = (struct AreaInfo *) AllocVec( sizeof(struct AreaInfo),MEMF_ANY );
if(areainfo!=0)
{
pattern = (UWORD *) AllocVec( sizeof(UWORD),MEMF_ANY);
if(pattern!=0)
{
*pattern = 0xffff; /*@@@ org: 0xffffffff*/
vbuffer = (APTR) AllocVec( MAX_POLYGON * 5 * sizeof(WORD),MEMF_ANY);
if(vbuffer!=0)
{
/* initialize */
InitArea( areainfo, vbuffer, MAX_POLYGON );
/* bind to rastport */
rp->AreaPtrn = pattern;
rp->AreaInfo = areainfo;
rp->AreaPtSz = 0;
}
else
OK=FALSE;
}
else
OK=FALSE;
}
else
OK=FALSE;
/* return(FALSE);*/
if (OK)
return (OK);
else
{
printf("Error when allocationg AreaBuffers\n");
if (vbuffer)
FreeVec(vbuffer);
if (pattern)
FreeVec(pattern);
if (areainfo)
FreeVec(areainfo);
return(OK);
}
}
void freearea(struct RastPort *rp)
{
if (rp->AreaInfo)
{
if (rp->AreaInfo->VctrTbl)
FreeVec(rp->AreaInfo->VctrTbl);
if (rp->AreaPtrn)
{
FreeVec(rp->AreaPtrn);
rp->AreaPtrn=NULL;
}
FreeVec(rp->AreaInfo);
rp->AreaInfo=NULL;
}
}
/*
* Destroy a temp raster.
*/
static void destroy_temp_raster( struct RastPort *rp )
{
/* bitmap */
unsigned long width, height;
width = rp->BitMap->BytesPerRow*8;
height = rp->BitMap->Rows;
if (rp->TmpRas)
{
if(rp->TmpRas->RasPtr)
FreeRaster( rp->TmpRas->RasPtr,width,height );
FreeVec( rp->TmpRas );
rp->TmpRas=NULL;
/* Current->tmpras = NULL;*/
}
}
void AllocOneLine( struct amigamesa_context *c)
{
if(c->imageline)
FreeVec(c->imageline);
c->imageline = AllocVec((c->width+15) & 0xfffffff0,MEMF_ANY); /* One Line */
}
void FreeOneLine( struct amigamesa_context *c)
{
if(c->imageline)
{
FreeVec(c->imageline);
c->imageline=NULL;
}
}
BOOL InitLibrary(void)
{
if(!GfxBase)
{
/* printf("Opening graphics.library\n");*/
if (!(GfxBase = OpenLibrary("graphics.library",39)))
{
printf("MesaOpenGL Error\nCouldent open graphics.library v39\n");
return(FALSE);
}
}
/* printf("GfxBase=0x%x\n",GfxBase);*/
return(TRUE);
}
void DisposeLibrary(void)
{
if (GfxBase) /* @@@ TODO Open and close gfxlibrary when open and flush lib.*/
CloseLibrary(GfxBase);
GfxBase=NULL;
}
/**********************************************************************/
/***** Amiga/Mesa API Functions *****/
/**********************************************************************/
/*
* Implement the client-visible Amiga/Mesa interface functions defined
* in Mesa/include/GL/Amigamesa.h
*/
__asm __saveds struct amigamesa_context *AmigaMesaCreateContext(register __a1 struct Window *window,register __d0 GLboolean rgb_flag,register __d1 GLboolean db_flag )
{
/* Create a new Amiga/Mesa context */
/* Be sure to initialize the following in the core Mesa context: */
/* RedScale, GreenScale, BlueScale, AlphaScale */
/* DrawBuffer, ReadBuffer */ /* @@@ IMPLEMENTERA ???*/
/* RGBAflag, DBflag */
GLfloat redscale,greenscale,bluescale,alphascale;
int I;
struct amigamesa_context *c;
/* printf("Hello and welcome to a Libfunction\n");*/
/* allocate amigamesa_context struct initialized to zeros */
c = (struct amigamesa_context *) AllocVec(sizeof(struct amigamesa_context),MEMF_PUBLIC|MEMF_CLEAR);
if (!c)
{
printf("Not able to create mesa_context. You are VERY low on memory.\n");
return(NULL);
}
c->sharelist=NULL; /* shared viewarea */
redscale=greenscale=bluescale=alphascale=255.0;
c->gl_ctx = gl_new_context( rgb_flag,
redscale, greenscale, bluescale, alphascale,
db_flag, NULL ); /*c->sharelist->gl_ctx ); @@@ tillfälligt */
c->rgb_flag = rgb_flag;
c->db_flag = db_flag;
c->front_rp =window->RPort;
c->back_rp=NULL;
c->rp = c->front_rp;
c->window = window;
c->width = window->Width - window->BorderLeft - window->BorderRight;
c->height = window->Height - window->BorderTop - window->BorderBottom;
c->left = window->BorderLeft;
c->bottom = window->Height - window->BorderBottom - 1;
c->depth = c->rp->BitMap->Depth;
c->gl_ctx->BufferWidth = c->width;
c->gl_ctx->BufferHeight = c->height;
if (rgb_flag)
{
/* RGBA color buffers */
c->gl_ctx->RGBAflag = GL_TRUE;
c->pixel = 0;
}
else
{
/* CI color buffers */
c->gl_ctx->RGBAflag = GL_FALSE;
c->pixel = 0;
}
if (db_flag)
{
if((c->back_rp = make_rastport(c->window->Width,c->window->Height,c->depth))!=NULL)
{
/* printf("make_rastport OK\n");*/
c->gl_ctx->Color.DrawBuffer = GL_BACK;
c->rp = c->back_rp;
}
else
{
printf("make_rastport Faild\n");
c->gl_ctx->Color.DrawBuffer = GL_FRONT;
}
}
else
{
c->gl_ctx->Color.DrawBuffer = GL_FRONT;
}
AllocOneLine(c); /* A linebuffer for WritePixelLine */
if (!make_temp_raster( c->rp ))
printf("Error allocating TmpRastPort\n");
allocarea(c->rp);
/*
printf("win width = %d\n", (int) window->Width );
printf("win height = %d\n", (int) window->Height );
printf("left = %d\n", (int) window->BorderLeft );
printf("rightt = %d\n", (int) window->BorderRight );
printf("top = %d\n", (int) window->BorderTop );
printf("bottom = %d\n", (int) c->bottom );
*/
for(I=0;I<=255;I++)
{
c->penconv[I]=I; /* Fill it with ordenery pen nr */
}
/* printf("Createcontext finishied\n");*/
return c;
}
__asm __saveds void AmigaMesaDestroyContext(register __a0 struct amigamesa_context *c )
{
/* destroy a Amiga/Mesa context */
int I;
if (c==Current)
Current=NULL;
FreeOneLine(c);
freearea(c->rp);
destroy_temp_raster( c->rp);
gl_destroy_context( c->gl_ctx );
if (c->rgb_flag)
{
if (c->rgb_buffer)
{
printf("free(c->rgb_buffer)\n");
free( c->rgb_buffer );
}
}
if (c->back_rp)
{
destroy_rastport( c->back_rp );
c->back_rp=NULL;
}
for(I=0;I<=255;I++)
{
/* printf("%d=%d\n",I,c->mypen[I]);*/
while (c->mypen[I]!=0) /* TODO This may free some others pen also */
{
c->mypen[I]-=1;
ReleasePen(c->window->WScreen->ViewPort.ColorMap,I);
}
}
FreeVec( c );
}
__asm __saveds void AmigaMesaMakeCurrent(register __a0 struct amigamesa_context *c )
{
/* Make the specified context the current one */
/* the order of operations here is very important! */
gl_set_context( c->gl_ctx );
Current = c;
amiga_setup_DD_pointers();
if (Current->gl_ctx->Viewport.Width==0) {
/* initialize viewport to window size */
gl_viewport( 0, 0, Current->width, Current->height );
}
}
__asm __saveds void AmigaMesaSwapBuffers(void)
{
/* copy/swap back buffer to front if applicable */
if (Current->back_rp)
{
UBYTE minterm = 0xc0;
int x = Current->window->BorderLeft;
int y = Current->window->BorderTop;
ClipBlit( Current->back_rp, x, y, /* from */
Current->front_rp, x, y, /* to */
Current->width, Current->height, /* size */
minterm );
}
}